//=============================================================================
// TFPRI. - used for nearly EVERYTHING (I shamefully admit: this is extremely shabby...)
//=============================================================================
class TFPRI extends xPlayerReplicationInfo;

var float RES;
var float Credits, OldCredits, Abilities[3], CombX[3], AuraEndTime;
var int UsedCredits;
var bool HasSuperWeapon;
var int BuildMode;
var vector MarkerLocations[16];
var bool inAura, shifted, drugged, spawnprotected;

replication
{
	// Things the server should send to the client.
	reliable if ( Role == ROLE_Authority )
		spawnprotected, AuraEndTime, HasSuperWeapon, RES, BuildMode, drugged, shifted, inAura, UsedCredits, credits, oldcredits, abilities, MarkerLocations;

    reliable if ( Role < ROLE_Authority )
		AddTech, Teleportation,SubRES, AddRES, SubSkill, AddSkill, SetBuildMode, AddWeapon, AddEquipment, AddSuperWeapon, DoUpgrade, ChangeAbility, ResetAbilities, UpdateAbilities;
}

function tick(float dt)
{
    local float ProtLeft, ProtTime;

    if(spawnprotected)
    {
        ProtTime=deathmatch(level.game).SpawnProtectionTime;
        ProtLeft=(controller(owner).pawn.SpawnTime+prottime)-level.TimeSeconds;

        if(controller(owner).pawn!=none) controller(owner).pawn.SetOverlayMaterial( Material'XGameShaders.PlayerShaders.PlayerShieldSh', protleft/prottime+0.1, false );

        if(protleft<=0 || (protleft<prottime/2 && (controller(owner).bFire==1 || controller(owner).bAltFire==1)))
            spawnprotected=false;
    }

    if(level.TimeSeconds>AuraEndTime) inAura=false;

    UpDateAbilities();
    SortMarkers();
}

function Teleportation(pawn p, tfstation origin, tfportal target)
{
    target.Teleportation(p, origin);
}

function AddTech(int type, int team)
{

}

function SubRES(float amount)
{
    RES+=amount;

    RES=fmax(res, 0);

    if(tfgame(level.game).UnlimitedRES==true)
    { if(RES<3000) RES=3000;  }
}

function AddRES(float amount)
{
    if(RES<3000)RES+=amount;
    if(RES>3000)RES=3000;

    RES=fmax(res, 0);
}

function SubSkill(float amount)
{
    Credits+=amount;

    if(tfgame(level.game).UnlimitedRES==true)
    if(credits<5000)credits=5000;
}

function AddSkill(float amount, optional float oldUsedSkill, optional bool noXP)
{
    local float addedAmount;
    if(oldUsedSkill==0 || oldUsedSkill<usedcredits) oldUsedSkill=usedcredits;
    if(oldUsedSkill>=250&&oldUsedSkill<500) addedAmount=amount/2;
    else if(oldUsedSkill>=500&&oldUsedSkill<1000) addedAmount=amount/4;
    else if(oldUsedSkill>=1000) addedAmount=amount/8;
    else addedAmount=amount;
    Credits+=addedAmount;
    if(noXP) OldCredits+=addedAmount;

    if(tfgame(level.game).UnlimitedRES==true)
    if(credits<5000)credits=5000;
}

function SetBuildMode(int newmode)
{
    BuildMode=newmode;
}

function AddWeapon(string aclassname)
{
    local class<TFWeapon> WeaponClass;
	local TFWeapon NewWeapon, oldweapon;
	local float creds;

    WeaponClass = class<TFWeapon>(DynamicLoadObject(aClassName, class'Class'));
	oldweapon=TFweapon(controller(owner).pawn.FindInventoryType(WeaponClass));
	creds=WeaponClass.default.SkillCost;

    if(credits>=creds && oldweapon==none)
    {
        newWeapon = controller(owner).pawn.Spawn(WeaponClass);
    }

    if(credits>=creds && TFAssaultRifle(oldweapon)!=none && !TFAssaultRifle(oldweapon).bDualMode)
    {
		Subskill(-creds);
	    usedcredits+=creds;
		TFAssaultRifle(oldweapon).bDualMode=true;
        //oldweapon.AddAmmo(50, 0);
		//oldweapon.AddAmmo(2, 1);

        controller(owner).pawn.pendingweapon=oldweapon;
		//controller(owner).pawn.weapon.PutDown();

		Playercontroller(owner).ClientPlaySound(Sound'MenuSounds.selectJ');
        return;
    }

    if( newWeapon != none )
	{
		Subskill(-creds);
	    usedcredits+=creds;
        newWeapon.GiveTo(controller(owner).pawn);
		controller(owner).pawn.pendingweapon=newWeapon;
		//controller(owner).pawn.weapon.PutDown();

		Playercontroller(owner).ClientPlaySound(Sound'MenuSounds.selectJ');
        return;
    }

    Playercontroller(owner).ClientPlaySound(Sound'TFMedia.TFGuiFail');
    return;
}



function AddSuperWeapon(tfstation station)
{
	local TFWeapon NewWeapon;
    local controller c;

    if(controller(owner).pawn.FindInventoryType(class'Taskforces.TFWLGun')==none)
    {
        newWeapon = controller(owner).pawn.Spawn(class'Taskforces.TFWLGun');
    }

    if( newWeapon != none)
    {
        tfwlgun(newweapon).grade=station.grade;

        newWeapon.GiveTo(controller(owner).pawn);
	    controller(owner).pawn.pendingweapon=newWeapon;
	    //controller(owner).pawn.weapon.PutDown();

		for ( c = Level.ControllerList; c!=None; c=c.nextController )
        {
            if(playercontroller(c)!=none && c.PlayerReplicationInfo.team.TeamIndex==team.teamindex)
                playercontroller(c).ReceiveLocalizedMessage(class'TaskForces.TFEquipNukeMsg',,self);
        }

        station.grade=0;
        station.destructed(none, true);

        Playercontroller(owner).ClientPlaySound(Sound'MenuSounds.selectJ');
        return;
    }

    Playercontroller(owner).ClientPlaySound(Sound'TFMedia.TFGuiFail');
    return;
}

function AddEquipment(string aclassname)
{
    local class<TFPowerups> InvClass;
	local TFPowerups NewInv;
	local float creds;

	InvClass = class<TFPowerups>(DynamicLoadObject(aClassName, class'Class'));
    creds=InvClass.default.SkillCost;

	if(credits>=creds && controller(owner).pawn.FindInventoryType(InvClass)==none && (!controller(owner).Pawn.weapon.bnotindemo|| aclassname!="Taskforces.TFAmmoPack"))
    {
        NewInv = controller(owner).pawn.Spawn(InvClass);
    }

    if( NewInv != none )
	{
		Subskill(-creds);
		if(!NewInv.IsA('TFMedPack')) usedcredits+=creds;

        NewInv.GiveTo(controller(owner).pawn);
        if( NewInv != none ) newInv.PickupFunction(controller(owner).pawn);
        if( NewInv != none ) newInv.Activate();

		Playercontroller(owner).ClientPlaySound(Sound'MenuSounds.selectJ');
        return;
    }

    Playercontroller(owner).ClientPlaySound(Sound'TFMedia.TFGuiFail');
    return;
}

function DoUpgrade(string passclass, float passcost, sentinel sent, pawn user)
{
  sent.CreateUpgrade(passclass, passcost,user);
}

function ChangeAbility(int type, float value)
{
    local float used;

    if(type>2) type-=3;

    if(value>0) used=fmin(-9,fmax(9,abilities[type]+1));
    else used=fmin(-9,fmax(9,abilities[type]-1));

    if(credits-value>=0 && ((value>0 && abilities[type]<9) || (value<0 && abilities[type]>-9)))
    {
	    credits-=value;
	    if(value>0) usedCredits+=value;

	    if(value>0) abilities[type]+=1;
	    else abilities[type]-=1;

	    updateAbilities();

	    Playercontroller(owner).ClientPlaySound(Sound'MenuSounds.selectJ');
        return;
	}

	Playercontroller(owner).ClientPlaySound(Sound'TFMedia.TFGuiFail');
	return;
}

function ResetAbilities()
{
    spawnprotected=true;

    usedcredits=0;
    drugged=false;

    abilities[0]=0;
	abilities[1]=0;
	abilities[2]=0;

	combx[0]=1;
	combx[1]=1;
	combx[2]=1;

	updateabilities();
}

function UpdateAbilities()
{
    if(controller(owner).pawn==none) return;

    //Power
	//controller(owner).pawn.damagescaling=calcFactor(0);

	//Durability
	//...controlled in ReduceDamage, too

	//Agility
	if(shifted)
	{
        controller(owner).pawn.airspeed=controller(owner).pawn.default.airspeed*calcfactor(2,2);
	    controller(owner).pawn.accelrate=controller(owner).pawn.default.accelrate*(calcfactor(2,1));
    }
    else controller(owner).pawn.airspeed=controller(owner).pawn.default.airspeed;

    controller(owner).pawn.groundspeed=controller(owner).pawn.default.groundspeed*(calcfactor(2,2));
	controller(owner).pawn.waterspeed=controller(owner).pawn.default.waterspeed*(calcfactor(2,2));;
	controller(owner).pawn.ladderspeed=controller(owner).pawn.default.ladderspeed*(calcfactor(2,2));
    controller(owner).pawn.accelrate=controller(owner).pawn.default.accelrate*(calcfactor(2,2));
    controller(owner).pawn.jumpz=controller(owner).pawn.default.jumpz*(calcfactor(2,8));
    controller(owner).pawn.aircontrol=controller(owner).pawn.default.aircontrol*(calcfactor(2,2));
}

function float calcFactor(int type, optional float divisor)
{
    local float outV/*, bonus*/;

    if(divisor==0) divisor=1;

    outv=1;

    if(inAura)
    {
        if(type==1) outv*=2;
        else outv*=1.5;
    }

    if(drugged)
    {
        if(type==1) outv*=3.0;
        else outv*=1.5;
    }

    if(shifted)
    {
        if(type==1) outv/=10;
        else if(type==2) outv*=8;
    }

    outv*=combx[type];

    return ((outv-1)/divisor)+1;
}

function SortMarkers()
{
	local Controller C,C2;
	local vector NextMarkerLoc;
	local float NextMarkerDist;
	local int i;
	local array<vector> ClosestMarkers;
	ClosestMarkers.Length = ArrayCount(MarkerLocations);

	for(C = Level.ControllerList; C != None; C = C.NextController)
	{   // if enemy(target) is none...If the pawn is a sentinel ....if the sentinel is the same team
		if(BaseSentinelController(C)==none || C.PlayerReplicationInfo==none || C.PlayerReplicationInfo.Team==none || C.PlayerReplicationInfo.Team.TeamIndex!=Team.TeamIndex)
			continue;
		if((Sentinel(C.Pawn)==none && TelemetrySentinel(C.Pawn)==none) || (Sentinel(C.Pawn)!=none && (C.Enemy == none || !Sentinel(C.Pawn).HasUpgrade(class'SentinelTelemeter'))))
			continue;
		if(!BaseSentinelController(C).bEnemyIsVisible && TelemetrySentinel(C.Pawn)==none)
			continue;
        //marker location = where the enemy is
        if(TelemetrySentinel(C.Pawn)==none)
        {
            if(C.Enemy.FindInventoryType(class'TFJammer')==none) //Condition added by Pimper. if player has a Jammer, the turret (with Telemetry upgrade) wont mark him.
            {
    	       NextMarkerLoc = C.LastSeenPos;
    	   	   NextMarkerDist = VSize(NextMarkerLoc - Owner.Location);// marker location is located here on enemy body
            }

    		for(i = 0; i < ArrayCount(MarkerLocations); i++) //sorts the marker locations by distance
    		{   //i think this checks the distance between 2 markers
    			if(ClosestMarkers[i] == vect(0, 0, 0) || NextMarkerDist < VSize(ClosestMarkers[i] - Owner.Location))
    			{
    				ClosestMarkers.Insert(i, 1);
    				ClosestMarkers[i] = NextMarkerLoc;
    				ClosestMarkers.Length = ArrayCount(MarkerLocations);
    				break;
    			}
    		}
    	}
    	else
    	{
    	   for(C2 = Level.ControllerList; C2 != None; C2 = C2.NextController)
    	   {
                if(C2.PlayerReplicationInfo!=none && C2.pawn!=none && C2.PlayerReplicationInfo.Team.TeamIndex!=Team.TeamIndex && BaseSentinelController(C2)==none && BaseSentinelController(C).LOSTo(C2.pawn))
                {
                    if(C2.Pawn.FindInventoryType(class'TFJammer')==none) //Condition added by Pimper. if player has a Jammer, he is not marked by Telemetry Sentinel.
                    {
                        NextMarkerLoc = C2.pawn.Location;
                        NextMarkerDist = VSize(NextMarkerLoc - Owner.Location);// marker location is located here on enemy body
                    }
                    if(NextMarkerDist<=C.pawn.SightRadius)
                    {
                		for(i = 0; i < ArrayCount(MarkerLocations); i++) //sorts the marker locations by distance
                		{
                			if(ClosestMarkers[i] == vect(0, 0, 0) || NextMarkerDist < VSize(ClosestMarkers[i] - Owner.Location))
                			{
                				ClosestMarkers.Insert(i, 1);
                				ClosestMarkers[i] = NextMarkerLoc;
                				ClosestMarkers.Length = ArrayCount(MarkerLocations);
                				break;
                			}
                        }
                    }
                }
    	   }
    	}
	}

	for(i = 0; i < ArrayCount(MarkerLocations); i++)
		MarkerLocations[i] = ClosestMarkers[i];        // checks which marker is the cloest i think
}

defaultproperties
{
     NetUpdateFrequency=10.000000
}
